﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Reflection;
using System.Text;

using Newtonsoft.Json;
using Newtonsoft.Json.Linq;

namespace Utils
{
    public static class EnumUtil
    {
        /// <summary>
        /// 获取枚举
        /// </summary>
        /// <param name="enumeration"></param>
        /// <returns></returns>
        public static string GetDescription(this Enum enumeration)
        {
            return enumeration.GetAttribute<DescriptionAttribute>()?.Description ?? enumeration.ToString();
        }

        public static int GetInt32Value(this Enum enumeration)
        {
            return Convert.ToInt32(enumeration);
        }

        public static List<EnumInfo> GetEnums<T>() where T : Enum
        {
            return GetEnums(typeof(T));
        }


        public static List<EnumInfo> GetEnums(Type type)
        {
            var fields = type.GetFields(BindingFlags.Public | BindingFlags.Static);
            return fields.Select(GetDynamic).ToList();
        }


        private static EnumInfo GetDynamic(FieldInfo fieldInfo)
        {
            int value = Convert.ToInt32(fieldInfo.GetValue(null));
            var info = new EnumInfo()
            {
                Value = value,
                Name = fieldInfo.Name
            };
            var attributes = fieldInfo.GetCustomAttributes();
            foreach (var item in attributes)
            {
                var attributeType = item.GetType();
                var property = attributeType.GetProperty(attributeType.Name.Substring(0, attributeType.Name.Length - "Attribute".Length), BindingFlags.Public | BindingFlags.Instance);
                if (property != null && property.CanRead)
                {
                    if (property.Name == "Description")
                    {
                        info.Description = property.GetValue(item)?.ToString();
                    }
                    else
                    {
                        if (info.Extends == null)
                            info.Extends = new JObject();
                        info.Extends[property.Name] = JToken.FromObject(property.GetValue(item));
                    }
                }
            }
            return info;
        }
        public static T GetAttribute<T>(this Enum enumeration) where T : Attribute
        {
            Type type = enumeration.GetType();
            return type.GetField(enumeration.ToString(), BindingFlags.Public | BindingFlags.Static).GetCustomAttribute<T>();
        }

        /// <summary>
        /// 位与
        /// </summary>
        /// <param name="e"></param>
        /// <param name="flag"></param>
        /// <returns></returns>
        public static bool HasFlag(this Enum e, Enum flag)
        {
            return HasFlag(e, Convert.ToInt32(flag));
        }

        /// <summary>
        /// 位与
        /// </summary>
        /// <param name="e"></param>
        /// <param name="flag"></param>
        /// <returns></returns>
        public static bool HasFlag(this Enum e, int flag)
        {
            return (Convert.ToInt32(e) & flag) != 0;
        }

        public static bool IsDefined<E>(int value) where E : Enum
        {
            var type = typeof(E);
            var fields = type.GetFields(BindingFlags.Public | BindingFlags.Static);

            foreach (var field in fields)
            {
                if (Convert.ToInt32(field.GetValue(null)) == value)
                {
                    return true;
                }
            }
            return false;
        }
    }

    public class EnumInfo
    {
        public int Value { get; set; }

        public string Name { get; set; }

        public string Description { get; set; }

        [JsonExtensionData]
        public JObject Extends { get; set; }

    }
}
